/**
 * Copyright (c) 2021 janeluo(janeluo.y@gmail.com)
 * itext7-pdf-replace is licensed under Mulan PSL v2.
 * You can use this software according to the terms and conditions of the Mulan PSL v2.
 * You may obtain a copy of Mulan PSL v2 at:
 * http://license.coscl.org.cn/MulanPSL2
 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
 * See the Mulan PSL v2 for more details.
 */
package com.niezhiliang.itext.pdf.replace;

import com.itextpdf.kernel.colors.ColorConstants;
import com.itextpdf.kernel.geom.Rectangle;
import com.itextpdf.kernel.pdf.PdfDocument;
import com.itextpdf.kernel.pdf.PdfPage;
import com.itextpdf.kernel.pdf.PdfReader;
import com.itextpdf.kernel.pdf.PdfWriter;
import com.itextpdf.kernel.pdf.canvas.PdfCanvas;
import com.itextpdf.kernel.pdf.canvas.parser.PdfCanvasProcessor;
import com.itextpdf.kernel.pdf.canvas.parser.listener.IPdfTextLocation;
import com.itextpdf.kernel.pdf.canvas.parser.listener.RegexBasedLocationExtractionStrategy;
import com.niezhiliang.itext.pdf.replace.dto.KeywordText;
import com.niezhiliang.itext.pdf.replace.dto.TextOverArea;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

/**
 * @author janeluo
 */
public class ReplaceUtils {

    /**
     * 覆盖文本
     *
     * @param sourceFilePath 源文件路径
     * @param destFilePath   目录文件路径
     * @param keywordTexts   替换文本集合
     * @throws IOException 文件IO异常
     */
    public static void doOverText(String sourceFilePath, String destFilePath, List<KeywordText> keywordTexts) throws IOException {
        PdfReader reader = new PdfReader(sourceFilePath);
        final PdfWriter writer = new PdfWriter(destFilePath);
        PdfDocument pdfDocument = new PdfDocument(reader, writer);
        doOverText(pdfDocument, keywordTexts);
    }

    /**
     * 覆盖文本
     *
     * @param sourceInputStream 源文件输入流
     * @param destOutputStream  目标文件输出流
     * @param keywordTexts      替换文本集合
     * @throws IOException 文件IO异常
     */
    public static void doOverText(InputStream sourceInputStream, OutputStream destOutputStream, List<KeywordText> keywordTexts) throws IOException {

        PdfReader reader = new PdfReader(sourceInputStream);
        final PdfWriter writer = new PdfWriter(destOutputStream);
        PdfDocument pdfDocument = new PdfDocument(reader, writer);
        doOverText(pdfDocument, keywordTexts);
    }

    /**
     * 覆盖文本
     *
     * @param pdfDocument  文档对象
     * @param keywordTexts 替换文本集合
     */
    public static void doOverText(PdfDocument pdfDocument, List<KeywordText> keywordTexts) {

        List<List<TextOverArea>> lists =
                getTextPosition(pdfDocument, keywordTexts);


        overText(pdfDocument, lists);

        pdfDocument.close();
    }

    /**
     * 获取关键字的坐标
     *
     * @param pdfDocument  文档
     * @param keywordTexts 替换文本集合
     * @return 被替换的文本在文档里的位置集合
     */
    private static List<List<TextOverArea>> getTextPosition(PdfDocument pdfDocument, List<KeywordText> keywordTexts) {


        List<List<TextOverArea>> list = new ArrayList<>();

        for (int i = 1; i <= pdfDocument.getNumberOfPages(); i++) {


            List<TextOverArea> textOverAreaList = new ArrayList<>();
            for (KeywordText text : keywordTexts) {
                PdfPage page = pdfDocument.getPage(i);

                RegexBasedLocationExtractionStrategy strategy = new RegexBasedLocationExtractionStrategy(text.getKeyword());
                PdfCanvasProcessor canvasProcessor = new PdfCanvasProcessor(strategy);
                canvasProcessor.processPageContent(page);
                Collection<IPdfTextLocation> resultantLocations = strategy.getResultantLocations();
//                PdfCanvas pdfCanvas = new PdfCanvas(page);
//                pdfCanvas.setLineWidth(0.5f);

                for (IPdfTextLocation location : resultantLocations) {
                    Rectangle rectangle = location.getRectangle();
//                    pdfCanvas.rectangle(rectangle);
//                    pdfCanvas.setStrokeColor(ColorConstants.RED);
//                    pdfCanvas.stroke();

                    TextOverArea textOverArea = new TextOverArea();
                    textOverArea.setPageNum(location.getPageNumber());
                    textOverArea.setX(rectangle.getX());
                    textOverArea.setY(rectangle.getY());
                    textOverArea.setWidth(rectangle.getWidth());
                    textOverArea.setHeight(rectangle.getHeight());
                    textOverArea.setKey(text.getKeyword());
                    textOverArea.setValue(text.getValue());
                    textOverArea.setFont(text.getFont());
                    textOverAreaList.add(textOverArea);
                }
            }

            list.add(textOverAreaList);
        }

        return list;
    }

    /**
     * 覆盖原有的内容 并填充新内容
     *
     * @param pdfDoc 源文件
     * @param list   替换的区域集合
     */
    private static void overText(PdfDocument pdfDoc, List<List<TextOverArea>> list) {
//        PdfDocument pdfDoc = new PdfDocument(new PdfReader(sourceInputStream), new PdfWriter(distOutputStream));
        //pdfDoc.getFirstPage().newContentStreamAfter() 会覆盖掉字体
        //pdfDoc.getFirstPage().newContentStreamBefore() 只会在字体的下层添加一个背景色
        for (int i = 1; i <= pdfDoc.getNumberOfPages(); i++) {
            PdfCanvas canvas = new PdfCanvas(pdfDoc.getPage(i).newContentStreamAfter(),
                    pdfDoc.getPage(i).getResources(), pdfDoc);

            canvas.saveState();
            List<TextOverArea> textOverAreas = list.get(i - 1);
            //用白色背景覆盖原本的字体
            for (TextOverArea overArea : textOverAreas) {
                canvas.setFillColor(ColorConstants.WHITE);
                //覆盖的时候y + 0.35   填充字体的时候 + 1.5 主要就是避免覆盖占位符下面的线
                canvas.rectangle(overArea.getX(), overArea.getY() + 0.35, overArea.getWidth(), overArea.getHeight());
            }
            canvas.fill();
            canvas.restoreState();

            //填充新内容
            canvas.beginText();
            for (TextOverArea overArea : textOverAreas) {
                canvas.setFontAndSize(overArea.getFont(), overArea.getHeight());
                canvas.setTextMatrix(overArea.getX(), overArea.getY() + 1.5f);
                canvas.newlineShowText(overArea.getValue());
            }
            canvas.endText();
        }


    }
}
